"""
当前模块，定义首页接口视图
"""
from rest_framework.views import APIView
from rest_framework.response import Response
from datetime import date
from users.models import User

# 用户总数统计接口实现
# 当前接口，是用来统计用户数量，并不是序列化/反序列化操作模型类对象的，
# 所以，我们只需要继承自APIView就可以了
class UserTotalView(APIView):

    def get(self, request):
        """
        统一用户总数
        :param request:
        :return:
        """
        # 1、统计出User用户的数量
        count = User.objects.count()
        # 2、构建响应
        return Response(data={
            'count': count,
            'date': date.today() # 直接获取年月日信息
        })


from django.conf import settings
from datetime import datetime
from django.utils import timezone
import pytz
# 日增用户(当日新创建的用户)
class UserDayIncrView(APIView):

    def get(self, request):
        # 1、当日0时刻获取
        # cur_time = datetime.now() # now函数返回的当前时刻，没有时区属性
        cur_time = timezone.now() # 当前的时刻，注意，是utc记录的当前时刻
        # 1.1 把cur_time转化为当前的本地时区
        cur_time = cur_time.astimezone(tz=pytz.timezone(settings.TIME_ZONE))
        # 1.2 获取本地的0时刻
        # 2020-4-14 0:0:0 +08:06
        local_0_time = cur_time.replace(hour=0, minute=0, second=0)

        # 2、根据User表过滤出，当日新建的用户
        count = User.objects.filter(
            # date_joined__gte=<当日的0时刻>
            # 用户新建的时间大于等于当日的0时刻，那么该用户就是当日新建的
            date_joined__gte=local_0_time
        ).count()

        return Response(data={
            'count': count,
            'date': cur_time.date() # 舍弃时分秒时区，只取年月日
        })



# 日活跃用户统计(最后登陆日期大于等于今天的零时)
class UserActiveView(APIView):

    def get(self, request):
        # 1、获取当日0时刻
        # cur_time = datetime.now() # now函数返回的当前时刻，没有时区属性
        cur_time = timezone.now()  # 当前的时刻，注意，是utc记录的当前时刻
        # 1.1 把cur_time转化为当前的本地时区
        cur_time = cur_time.astimezone(tz=pytz.timezone(settings.TIME_ZONE))
        # 1.2 获取本地的0时刻
        # 2020-4-14 0:0:0 +08:06
        local_0_time = cur_time.replace(hour=0, minute=0, second=0)

        # 2、过滤出当日活跃的用户数量
        count = User.objects.filter(
            last_login__gte=local_0_time
        ).count()

        # 3、构建响应
        return Response(data={
            'count': count,
            'date': cur_time.date()
        })



from orders.models import OrderInfo
# 日下单用户统计(当日下了订单的用户的数量)
class UserDayOrderView(APIView):

    def get(self, request):
        # 1、获取当日零时刻 ---> 过滤出今天下了的订单
        cur_time = timezone.now()  # 当前的时刻，注意，是utc记录的当前时刻
        # 1.1 把cur_time转化为当前的本地时区
        cur_time = cur_time.astimezone(tz=pytz.timezone(settings.TIME_ZONE))
        # 1.2 获取本地的0时刻
        # 2020-4-14 0:0:0 +08:06
        local_0_time = cur_time.replace(hour=0, minute=0, second=0)

        # 2、统计当日下单的用户数(关联查询)
        # 思考：使用从表的条件，关联查询主表数据！
        # 1、查询条件：当日零时刻(从表的查询条件)
        # 2、目标数据：用户数量(主表目标数据)

        # # 方案一：从表入手查询
        # # order_list: 是当日下的所有的订单，是一个查询集(QuerySet)
        # order_list = OrderInfo.objects.filter(
        #     create_time__gte=local_0_time
        # )
        # user_set = set() # 初始化一个集合对象
        # for order in order_list:
        #     # order: 是一个订单对象
        #     user_set.add(order.user) # 往一个集合中，添加元素——自动去重复
        #
        # count = len(user_set)

        # 方案二：从主表入手查询
        user_list = User.objects.filter(
            # 零时刻作为订单的过滤条件，如何应用在用户表查询中？！
            # orders__开头的，后面拼接从表的过滤字段 —— 使用从表过滤条件，过滤出主表数据
            orders__create_time__gte=local_0_time
        )
        # django模型类filter的时候，不会去重！上述语法本质，就是先查询从表数据，在逐个查询主表数据，且不过滤！
        count = len(set(user_list))

        # 3、构建响应
        return Response(data={
            'count': count,
            'date': cur_time.date()
        })



from datetime import timedelta
# 月新增用户统计(最近30天包含当日每一天新增用户数据)
class UserMonthIncrView(APIView):

    def get(self, request):
        # 思考：计算出最近30天，每一天的零时刻，然后过滤出每一天的新增用户数量

        # 1、获取当日0时刻
        cur_time = timezone.now()
        cur_time = cur_time.astimezone(tz=pytz.timezone(settings.TIME_ZONE))
        # end_0_time是最近30天中，最后一天，也就是当日的零时刻
        end_0_time = cur_time.replace(hour=0, minute=0, second=0)

        # 2、获取启始日的零时
        # 规律：获取最近的n天(包含当日)的启始日期时间点： 启始日期零时 = 当日零时 - (n-1)天
        start_0_time = end_0_time - timedelta(days=29)

        ret = [] # 保存返回数据
        # 所有的日期在start_0_time和end_0_time之间总共30天(包含第一天和最后一天)
        # 3、遍历出在[start_0_time, end_0_time]之间的所有日期的零时刻, 遍历30次获取
        for index in range(30):
            # 每一次遍历获取30天中一天的零时刻,从第一天开始
            # calc_0_time：某一天的零时刻
            # calc_0_time = start_0_time  + timedelta(days=0)                 # 第1天 index: 0
            # calc_0_time = start_0_time  + timedelta(days=1)                 # 第2天 index: 1
            # calc_0_time = start_0_time  + timedelta(days=2)                 # 第3天 index: 2
            # calc_0_time = start_0_time  + timedelta(days=3)                 # 第4天 index: 3
            # calc_0_time = start_0_time + timedelta(days=29)                 # 第30天 index: 29
            calc_0_time = start_0_time + timedelta(days=index)
            next_0_time = calc_0_time + timedelta(days=1)
            # 我们在判断过去的一天，新增用户的时候，需要设置上限和下限
            # 该天零时 <= 新建时间 < 次日的零时
            count = User.objects.filter(
                date_joined__gte=calc_0_time,
                # date_joined__lt=<次日零时>
                date_joined__lt=next_0_time

            ).count()

            # 根据calc_0_time过滤出改日新增的用户数据
            ret.append({
                'count': count,
                'date': calc_0_time.date()
            })

        return Response(data=ret)


from rest_framework.generics import ListAPIView
from meiduo_admin.serializers.home_serializers import *
# 当日分类商品访问量: 序列化返回GoodsVisitCount对象(多条数据)
class GoodsVisitCountView(ListAPIView):

    queryset = GoodsVisitCount.objects.all()
    serializer_class = GoodsVisitCountModelSerializer

    # 序列化返回的分类商品访问量，是当日，所以当前视图
    # 序列化返回的查询集，必须根据当日零时过滤
    # ListAPIView是使用方法self.get_queryset()来获取序列化操作的查询集
    # 意味着，我们重写该方法，就可以实现查询集的过滤
    def get_queryset(self):
        # 过滤出当日新产生的商品分类访问量信息
        cur_time = timezone.now()
        cur_time = cur_time.astimezone(tz=pytz.timezone(settings.TIME_ZONE))
        cur_0_time = cur_time.replace(hour=0, minute=0, second=0)
        return self.queryset.filter(create_time__gte=cur_0_time)







